package org.idea.spring.task.config;

import lombok.extern.slf4j.Slf4j;
import org.idea.spring.task.annotation.CronBean;
import org.idea.spring.task.model.CronSetting;
import org.idea.spring.task.service.CronSettingService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.concurrent.ScheduledFuture;

/**
 * 定时任务bean初始化处理器
 *
 * @author idea
 * @data 2019/1/15
 */
@Component
@Slf4j
public class CronBeanHandle implements BeanPostProcessor {

    @Autowired
    private CronSettingService cronSettingService;

    private static boolean MYBATIS_CONFIG_INIT_STATUS = false;


    private static ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();

    private void initThreadPool() {
            int count = cronSettingService.selectAllCron().size();
            threadPoolTaskScheduler.setPoolSize(count);
            threadPoolTaskScheduler.setThreadNamePrefix("task-");
            threadPoolTaskScheduler.setAwaitTerminationSeconds(10);
            threadPoolTaskScheduler.initialize();
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass().isAnnotationPresent(CronBean.class)) {
            if (checkObjectIsImplementRunnable(bean)) {
                //初始化配置操作
                if (!MYBATIS_CONFIG_INIT_STATUS) {
                    SqlSessionConfig.FILE_NAME = "configs/ApplicationSetting-conf.xml";
                    SqlSessionUtil sqlSessionUtil = new SqlSessionUtil();
                    initThreadPool();
                    MYBATIS_CONFIG_INIT_STATUS = true;
                }
                CronBean cronBean = bean.getClass().getAnnotation(CronBean.class);
                String cronBeanName = cronBean.name();
                CronSetting cronSetting = cronSettingService.selectOneByName(cronBeanName);
                if (cronSetting != null) {
                    //判断该定时任务是否已经开启
                    ScheduledFuture<?> future = threadPoolTaskScheduler.schedule((Runnable) bean, new CronTrigger(cronSetting.getCron()));
                    CronSettingService.putTaskBean(cronBeanName, future);
                }
            }
        }
        return null;
    }

    /**
     * 校验某个类是否已经实现了Runnable接口
     *
     * @return
     */
    private boolean checkObjectIsImplementRunnable(Object obj) {
        Class<?> interfaces[] = obj.getClass().getInterfaces();
        for (Class<?> anInterface : interfaces) {
            if (anInterface.getName().equals(Runnable.class.getName())) {
                return true;
            }
        }
        return false;
    }
}
